home *** CD-ROM | disk | FTP | other *** search
/ ShareWare OnLine 2 / ShareWare OnLine Volume 2 (CMS Software)(1993).iso / prog / exec33.zip / EXEC.C < prev    next >
C/C++ Source or Header  |  1991-11-21  |  14KB  |  571 lines

  1. /*
  2.    --- Version 3.3 91-11-21 16:12 ---
  3.  
  4.    EXEC.C: EXEC function with memory swap - Prepare parameters.
  5.  
  6.    Public domain software by
  7.  
  8.         Thomas Wagner
  9.         Ferrari electronic GmbH
  10.         Beusselstrasse 27
  11.         D-1000 Berlin 21
  12.         Germany
  13. */
  14.  
  15. #include "compat.h"
  16. #include "exec.h"
  17. #include "checkpat.h"
  18. #include <bios.h>
  19.  
  20. /*>e
  21.    Set REDIRECT to 1 to support redirection, else to 0.
  22.    CAUTION: The definition in 'spawn.asm' must match this definition!!
  23. <*/
  24. /*>d
  25.    Setzen Sie REDIRECT auf 1 um Dateiumleitung zu untertützen, sonst auf 0.
  26.    ACHTUNG: Die Definition in 'spawn.asm' muß mit dieser Definition 
  27.    übereinstimmen!!
  28. <*/
  29.  
  30.  
  31. #define REDIRECT  1
  32.  
  33. #define SWAP_FILENAME "$$AAAAAA.AAA" 
  34.  
  35. /*e internal flags for prep_swap */
  36. /*d interne Flags für prep_swap */
  37.  
  38. #define CREAT_TEMP      0x0080
  39. #define DONT_SWAP_ENV   0x4000
  40.  
  41. #define ERR_COMSPEC     -7
  42. #define ERR_NOMEM       -8
  43.  
  44.  
  45. spawn_check_proc *spawn_check = NULL;
  46.  
  47. /*e local variables */
  48. /*d Lokale Variablen */
  49.  
  50. static char drive [MAXDRIVE], dir [MAXDIR];
  51. static char name [MAXFILE], ext [MAXEXT];
  52. static char cmdpath [MAXPATH] = "";
  53. static char cmdpars [80] = "";
  54.  
  55.  
  56. #ifdef __cplusplus
  57. extern "C" int
  58. #else
  59. extern int _cdecl
  60. #endif
  61. do_spawn (int swapping,     /*e swap if non-0 */
  62.                             /*d Auslagern wenn nicht 0 */
  63.           char *xeqfn,      /*e file to execute */
  64.                             /*d auszuführende Datei */
  65.           char *cmdtail,    /*e command tail string */
  66.                             /*d Kommandozeile */
  67.           unsigned envlen,  /*e environment length */
  68.                             /*d Länge Umgebungsvariablen */
  69.           char *envp        /*e environment pointer */
  70.                             /*d Zeiger auf Umgebungsvariablen */
  71. #if (REDIRECT)
  72.           ,char *rstdin,    /*e redirection file names */
  73.                             /*d Umleitungs-Dateinamen */
  74.           char *rstdout,
  75.           char *rstderr
  76. #endif
  77.           );
  78.  
  79. #ifdef __cplusplus
  80. extern "C" int
  81. #else
  82. extern int _cdecl
  83. #endif
  84. prep_swap (int method,      /*e swap method */
  85.                             /*d Auslagerungsmethode */
  86.            char *swapfn);   /*e swap file name and/or path */
  87.                             /*d Auslagerungsdateiname und/oder Pfad */
  88.  
  89. #ifdef __cplusplus
  90. extern "C" int
  91. #else
  92. extern int _cdecl
  93. #endif
  94. exists (char *fname);
  95.  
  96. /* --------------------------------------------------------------------- */
  97.  
  98. /*>e Try '.COM', '.EXE', and '.BAT' on current filename, modify 
  99.    filename if found. <*/
  100. /*>d '.COM', '.EXE' und '.BAT' mit dem aktuellen Dateinamen versuchen,
  101.    Dateinamen modifizieren wenn gefunden. <*/
  102.  
  103. static int tryext (char *fn)
  104. {
  105.    char *ext;
  106.  
  107.    ext = strchr (fn, '\0');
  108.    strcpy (ext, ".COM");
  109.    if (exists (fn))
  110.       return 1;
  111.    strcpy (ext, ".EXE");
  112.    if (exists (fn))
  113.       return 1;
  114.    strcpy (ext, ".BAT");
  115.    if (exists (fn))
  116.       return 2;
  117.    *ext = 0;
  118.    return 0;
  119. }
  120.  
  121. /*>e Try to find the file 'fn' in the current path. Modifies the filename
  122.    accordingly. <*/
  123. /*>d Versuchen die Datei 'fn' im aktuellen Pfad zu finden. Der Dateiname
  124.    wird entsprechend modifiziert. <*/
  125.  
  126. static int findfile (char *fn)
  127. {
  128.    char *path, *penv;
  129.    char *prfx;
  130.    int found, check, hasext;
  131.  
  132.    if (!*fn)
  133.       return (cmdpath [0]) ? 3 : ERR_COMSPEC;
  134.  
  135.    check = checkpath (fn, INF_NODIR, drive, dir, name, ext, fn);
  136.    if (check < 0)
  137.       return check;
  138.  
  139.    if ((check & HAS_WILD) || !(check & HAS_FNAME))
  140.       return ERR_FNAME;
  141.  
  142.    hasext = (check & HAS_EXT) ? ((!stricmp (ext, ".bat")) ? 2 : 1) : 0;
  143.  
  144.    if (hasext)
  145.       {
  146.       if (check & FILE_EXISTS)
  147.          found = hasext;
  148.       else
  149.          found = 0;
  150.       }
  151.    else
  152.       found = tryext (fn);
  153.  
  154.    if (found || (check & (HAS_PATH | HAS_DRIVE)))
  155.       return found;
  156.  
  157.    penv = getenv ("PATH");
  158.    if (!penv)
  159.       return 0;
  160.    path = (char *)malloc (strlen (penv) + 1);
  161.    if (path == NULL)
  162.       return ERR_NOMEM;
  163.  
  164.    strcpy (path, penv);
  165.    prfx = strtok (path, ";");
  166.  
  167.    while (!found && prfx != NULL)
  168.       {
  169.       while (isspace (*prfx))
  170.          prfx++;
  171.       if (*prfx)
  172.          {
  173.          strcpy (fn, prfx);
  174.          prfx = strchr (fn, '\0');
  175.          prfx--;
  176.          if (*prfx != '\\' && *prfx != '/' && *prfx != ':')
  177.             {
  178.             *++prfx = '\\';
  179.             }
  180.          prfx++;
  181.          strcpy (prfx, name);
  182.          strcat (prfx, ext);
  183.          check = checkpath (fn, INF_NODIR, drive, dir, name, ext, fn);
  184.          if (check > 0 && (check & HAS_FNAME))
  185.             {
  186.             if (hasext)
  187.                {
  188.                if (check & FILE_EXISTS)
  189.                   found = hasext;
  190.                }
  191.             else
  192.                found = tryext (fn);
  193.             }
  194.          }
  195.       prfx = strtok (NULL, ";");
  196.       }
  197.    free (path);
  198.    return found;
  199. }
  200.  
  201.  
  202. /*>e 
  203.    Get name and path of the command processor via the COMSPEC 
  204.    environmnt variable. Any parameters after the program name
  205.    are copied and inserted into the command line.
  206. <*/
  207. /*>d
  208.    Namen und Pfad des Kommandoprozessors über die COMSPEC-Umgebungs-
  209.    Variable bestimmen. Parameter nach dem Programmnamen werden kopiert
  210.    und in die Kommandozeile eingefügt.
  211. <*/
  212.  
  213. static void getcmdpath (void)
  214. {
  215.    char *pcmd;
  216.    int found = 0;
  217.  
  218.    if (cmdpath [0])
  219.       return;
  220.    pcmd = getenv ("COMSPEC");
  221.    if (pcmd)
  222.       {
  223.       strcpy (cmdpath, pcmd);
  224.       pcmd = cmdpath;
  225.       while (isspace (*pcmd))
  226.          pcmd++;
  227.       if (NULL != (pcmd = strpbrk (pcmd, ";,=+/\"[]|<> \t")))
  228.          {
  229.          while (isspace (*pcmd))
  230.             *pcmd++ = 0;
  231.          if (strlen (pcmd) >= 79)
  232.             pcmd [79] = 0;
  233.          strcpy (cmdpars, pcmd);
  234.          strcat (cmdpars, " ");
  235.          }
  236.       found = findfile (cmdpath);
  237.       }
  238.    if (!found)
  239.       {
  240.       cmdpars [0] = 0;
  241.       strcpy (cmdpath, "COMMAND.COM");
  242.       found = findfile (cmdpath);
  243.       if (!found)
  244.          cmdpath [0] = 0;
  245.       }
  246. }
  247.  
  248.  
  249. /*>e
  250.    tempdir: Set temporary file path.
  251.             Read "TMP/TEMP" environment. If empty or invalid, clear path.
  252.             If TEMP is drive or drive+backslash only, return TEMP.
  253.             Otherwise check if given path is a valid directory.
  254.             If so, add a backslash, else clear path.
  255. <*/
  256. /*>d
  257.    tempdir: Pfad für temporäre Datei setzen.
  258.             Die Umgebungsvariable "TMP" oder "TEMP" wird gelesen. Ist
  259.             keine der beiden vorhanden, oder sind sie ungültig, wird
  260.             der Pfad gelöscht.
  261.             Besteht TMP/TEMP nur aus Laufwerksbuchstaben, oder aus
  262.             Laufwerk und Backslash, liefern TEMP.
  263.             Sonst prüfen ob der Pfad gültig ist, und einen Backslash
  264.             anfügen.
  265. <*/
  266.  
  267. static int tempdir (char *outfn)
  268. {
  269.    int i, res;
  270.    char *stmp [4];
  271.  
  272.    stmp [0] = getenv ("TMP");
  273.    stmp [1] = getenv ("TEMP");
  274.    stmp [2] = ".\\";
  275.    stmp [3] = "\\";
  276.  
  277.    for (i = 0; i < 4; i++)
  278.       if (stmp [i])
  279.          {
  280.          strcpy (outfn, stmp [i]);
  281.          res = checkpath (outfn, 0, drive, dir, name, ext, outfn);
  282.          if (res > 0 && (res & IS_DIR) && !(res & IS_READ_ONLY))
  283.             return 1;
  284.          }
  285.    return 0;
  286. }
  287.  
  288.  
  289. #if (REDIRECT)
  290.  
  291. static int redirect (char *par, char **rstdin, char **rstdout, char **rstderr)
  292. {
  293.    char ch, sav;
  294.    char *fn, *fnp;
  295.    int app;
  296.  
  297.    do
  298.       {
  299.       app = 0;
  300.       ch = *par;
  301.       *par++ = 0;
  302.       if (ch != '<')
  303.          {
  304.          if (*par == '&')
  305.             {
  306.             ch = '&';
  307.             par++;
  308.             }
  309.          if (*par == '>')
  310.             {
  311.             app = 1;
  312.             par++;
  313.             }
  314.          }
  315.  
  316.       while (isspace (*par))
  317.          par++;
  318.       fn = par;
  319.       if ((fnp = strpbrk (par, ";,=+/\"[]|<> \t")) != NULL)
  320.          par = fnp;
  321.       else
  322.          par = strchr (par, '\0');
  323.       sav = *par;
  324.       *par = 0;
  325.  
  326.       if (!strlen (fn))
  327.          return 0;
  328.       fnp = (char *)malloc (strlen (fn) + app + 1);
  329.       if (fnp == NULL)
  330.          return 0;
  331.       if (app)
  332.          {
  333.          strcpy (fnp, ">");
  334.          strcat (fnp, fn);
  335.          }
  336.       else
  337.          strcpy (fnp, fn);
  338.  
  339.       switch (ch)
  340.          {
  341.          case '<':   if (*rstdin != NULL)
  342.                         return 0;
  343.                      *rstdin = fnp;
  344.                      break;
  345.          case '>':   if (*rstdout != NULL)
  346.                         return 0;
  347.                      *rstdout = fnp;
  348.                      break;
  349.          case '&':   if (*rstderr != NULL)
  350.                         return 0;
  351.                      *rstderr = fnp;
  352.                      break;
  353.          }
  354.  
  355.       *par = sav;
  356.       while (isspace (*par))
  357.          par++;
  358.       }
  359.    while (*par == '>' || *par == '<');
  360.  
  361.    return 1;
  362. }
  363.  
  364. #endif
  365.  
  366.  
  367. int do_exec (char *exfn, char *epars, int spwn, unsigned needed, char **envp)
  368. {
  369.    static char swapfn [MAXPATH];
  370.    static char execfn [MAXPATH];
  371.    unsigned avail;
  372.    union REGS regs;
  373.    unsigned envlen;
  374.    int rc, ffrc;
  375.    int idx;
  376.    char **env;
  377.    char *ep, *envptr, *envbuf;
  378.    char *progpars;
  379.    int swapping;
  380. #if (REDIRECT)
  381.    char *rstdin = NULL, *rstdout = NULL, *rstderr = NULL;
  382. #endif
  383.  
  384.    envlen = 0;
  385.    envptr = NULL;
  386.    envbuf = NULL;
  387.  
  388.    if (epars == NULL)
  389.       epars = "";
  390.    if (exfn == NULL)
  391.       execfn [0] = 0;
  392.    else
  393.       strcpy (execfn, exfn);
  394.  
  395.    getcmdpath ();
  396.  
  397.    /*e First, check if the file to execute exists. */
  398.    /*d Zunächst prüfen ob die auszuführende Datei existiert. */
  399.  
  400.    if ((ffrc = findfile (execfn)) <= 0)
  401.       return RC_NOFILE | -ffrc;
  402.  
  403.    if (ffrc > 1)   /* COMMAND.COM or Batch file */
  404.       {
  405.       if (!cmdpath [0])
  406.          return RC_NOFILE | -ERR_COMSPEC;
  407.  
  408.       idx = (ffrc == 2) ? strlen (execfn) + 5 : 1;
  409.       progpars = (char *)malloc (strlen (epars) + strlen (cmdpars) + idx);
  410.       if (progpars == NULL)
  411.          return RC_NOFILE | -ERR_NOMEM;
  412.       strcpy (progpars, cmdpars);
  413.       if (ffrc == 2)
  414.          {
  415.          strcat (progpars, "/c ");
  416.          strcat (progpars, execfn);
  417.          strcat (progpars, " ");
  418.          }
  419.       strcat (progpars, epars);
  420.       strcpy (execfn, cmdpath);
  421.       }
  422.    else
  423.       {
  424.       progpars = (char *)malloc (strlen (epars) + 1);
  425.       if (progpars == NULL)
  426.          return RC_NOFILE | -ERR_NOMEM;
  427.       strcpy (progpars, epars);
  428.       }
  429.  
  430. #if (REDIRECT)
  431.    if ((ep = strpbrk (progpars, "<>")) != NULL)
  432.       if (!redirect (ep, &rstdin, &rstdout, &rstderr))
  433.          {
  434.          rc = RC_REDIRERR;
  435.          goto exit;
  436.          }
  437. #endif
  438.  
  439.    /*e Now create a copy of the environment if the user wants it. */
  440.    /*d Nun eine Kopie der Umgebungsvariablen anlegen wenn angefordert. */
  441.  
  442.    if (envp != NULL)
  443.       for (env = envp; *env != NULL; env++)
  444.          envlen += strlen (*env) + 1;
  445.  
  446.    if (envlen)
  447.       {
  448.       /*e round up to paragraph, and alloc another paragraph leeway */
  449.       /*d Auf Paragraphengrenze runden, plus einen Paragraphen zur Sicherheit */
  450.       envlen = (envlen + 32) & 0xfff0;
  451.       envbuf = (char *)malloc (envlen);
  452.       if (envbuf == NULL)
  453.          {
  454.          rc = RC_ENVERR;
  455.          goto exit;
  456.          }
  457.  
  458.       /*e align to paragraph */
  459.       /*d Auf Paragraphengrenze adjustieren */
  460.       envptr = envbuf;
  461.       if (FP_OFF (envptr) & 0x0f)
  462.          envptr += 16 - (FP_OFF (envptr) & 0x0f);
  463.       ep = envptr;
  464.  
  465.       for (env = envp; *env != NULL; env++)
  466.          {
  467.          ep = stpcpy (ep, *env) + 1;
  468.          }
  469.       *ep = 0;
  470.       }
  471.  
  472.    if (!spwn)
  473.       swapping = -1;
  474.    else
  475.       {
  476.       /*e Determine amount of free memory */
  477.       /*d Freien Speicherbereich feststellen */
  478.  
  479.       regs.x.ax = 0x4800;
  480.       regs.x.bx = 0xffff;
  481.       intdos (®s, ®s);
  482.       avail = regs.x.bx;
  483.  
  484.       /*e No swapping if available memory > needed */
  485.       /*d Keine Auslagerung wenn freier Speicher > benötigter */
  486.  
  487.       if (needed < avail)
  488.          swapping = 0;
  489.       else
  490.          {
  491.          /*>e Swapping necessary, use 'TMP' or 'TEMP' environment variable
  492.            to determine swap file path if defined. <*/
  493.          /*>d Auslagerung notwendig, 'TMP' oder 'TEMP' Umgebungsvariable
  494.             verwenden um Auslagerungsdateipfad festzulegen. <*/
  495.  
  496.          swapping = spwn;
  497.          if (spwn & USE_FILE)
  498.             {
  499.             if (!tempdir (swapfn))
  500.                {
  501.                spwn &= ~USE_FILE;
  502.                swapping = spwn;
  503.                }
  504.             else if (OS_MAJOR >= 3)
  505.                swapping |= CREAT_TEMP;
  506.             else
  507.                {
  508.                strcat (swapfn, SWAP_FILENAME);
  509.                idx = strlen (swapfn) - 1;
  510.                while (exists (swapfn))
  511.                   {
  512.                   if (swapfn [idx] == 'Z')
  513.                      idx--;
  514.                   if (swapfn [idx] == '.')
  515.                      idx--;
  516.                   swapfn [idx]++;
  517.                   }
  518.                }
  519.             }
  520.          }
  521.       }
  522.  
  523.    /*e All set up, ready to go. */
  524.    /*d Alles vorbereitet, jetzt kann's losgehen. */
  525.  
  526.    if (swapping > 0)
  527.       {
  528.       if (!envlen)
  529.          swapping |= DONT_SWAP_ENV;
  530.  
  531.       rc = prep_swap (swapping, swapfn);
  532.       if (rc < 0)
  533.          rc = RC_PREPERR | -rc;
  534.       else
  535.          rc = 0;
  536.       }
  537.    else
  538.       rc = 0;
  539.  
  540.    if (!rc)
  541.       {
  542.       if (spawn_check != NULL)
  543.          rc = spawn_check (ffrc, swapping, execfn, progpars);
  544.       if (!rc)
  545. #if (REDIRECT)
  546.          rc = do_spawn (swapping, execfn, progpars, envlen, envptr, rstdin, rstdout, rstderr);
  547. #else
  548.          rc = do_spawn (swapping, execfn, progpars, envlen, envptr);
  549. #endif
  550.       }
  551.  
  552.    /*e Free the environment buffer if it was allocated. */
  553.    /*d Den Umgebungsvariablenblock freigeben falls er alloziert wurde. */
  554.  
  555. exit:
  556.    free (progpars);
  557. #if (REDIRECT)
  558.    if (rstdin)
  559.       free (rstdin);
  560.    if (rstdout)
  561.       free (rstdout);
  562.    if (rstderr)
  563.       free (rstderr);
  564. #endif
  565.    if (envlen)
  566.       free (envbuf);
  567.  
  568.    return rc;
  569. }
  570.  
  571.